I.11不要使用原始指针或引用传递所有权

面向对象思考 2019-11-18 22:20:02

C++核心准则边译边学-I.11 不要使用原始指针或引用传递所有权

I.11: Never transfer ownership by a raw pointer (T*) or reference (T&)(永远不要使用原始指针或引用传递所有权)

Reason(原因)

If there is any doubt whether the caller or the callee owns an object, leaks or premature destruction will occur.

如果一个对象是属于调用者还是被调用者存在任何疑问的话,就可能发生泄漏或过早销毁。

Example(示例)

Consider:(考虑)

X* compute(args) // don't
{
    X* res = new X{};
    // ...
    return res;
}

Who deletes the returned X? The problem would be harder to spot if compute returned a reference. Consider returning the result by value (use move semantics if the result is large):

应该由谁删除返回的X? 当compute返回一个参照的时候,这个问题会很难判断。考虑返回一个值(如果结果很大则使用移动语法)

译者注:移动语法指的是C++11开始引入的右值引用和std::move。进一步信息请参照下面的文章:

https://mp.weixin.qq.com/s/MO4oxf5KjLRvpAvyyOMZiA

https://mp.weixin.qq.com/s/WNVUfG11aTZ9bq6lBtaCyg

vector<double> compute(args) // good
{
    vector<double> res(10000);
    // ...
    return res;
}

Alternative: Pass ownership using a "smart pointer", such as unique_ptr (for exclusive ownership) and shared_ptr (for shared ownership). However, that is less elegant and often less efficient than returning the object itself, so use smart pointers only if reference semantics are needed.

其他选项:使用“智能指针”传递所有权,例如unique_ptr(用于独占所有权)和shared_prt(用于共享所有权)。然而这种做法和直接返回对象本身相比稍微欠缺一点优雅和效率,因此应该只在需要参照语义时才需要智能指针。

译者注:智能指针可以参考以下文章。

shared_ptr:

https://mp.weixin.qq.com/s/rreUOPpoNTvPWXLjgV_bsA

https://mp.weixin.qq.com/s/3J1_nZNrDs5X-rw_XUw9UQ

https://mp.weixin.qq.com/s/hURdinSkkw960qD5Wq1YOA

unique_ptr:

https://mp.weixin.qq.com/s/wgc8p1Pw9GD5LIx1C33wxQ

Alternative: Sometimes older code can't be modified because of ABI compatibility requirements or lack of resources. In that case, mark owning pointers using owner from the guidelines support library:

其他选项:有时因为ABI兼容性的要求或者需要避免资源泄漏而无法修改旧代码。在这种情况下,使用准则支持库提供的owner形式来标记控制所有权的指针。

译者注:ABI,由操作系统提供的应用程序二进制接口(Application Binary Interface)

owner<X*> compute(args) // It is now clear that ownership is transferred
{
    owner<X*> res = new X{};
    // ...
    return res;
}

This tells analysis tools that res is an owner. That is, its value must be deleted or transferred to another owner, as is done here by the return.

这样可以告诉分析工具res是所有者。也就是说,它的值必须被删除或者转移给其他的所有者,就像这里通过return返回结果时所做的一样。

owner is used similarly in the implementation of resource handles.

在实现资源句柄的时候,owner也会以相似的方式被使用。

Note(注意)

Every object passed as a raw pointer (or iterator) is assumed to be owned by the caller, so that its lifetime is handled by the caller. Viewed another way: ownership transferring APIs are relatively rare compared to pointer-passing APIs, so the default is "no ownership transfer."

所有通过原始指针(或迭代器)传递的对象都被假设由调用者所有,因此它的生命周期也由调用者管理。换一个角度:相对而言,和指针传递API相比,所有权转移API相当少,因此(大家)默认的情况是没有所有权转移。

See also: Argument passing, use of smart pointer arguments, and value return.

参考:参数传递,使用智能指针参数,值返回。

Enforcement(实施建议)

(Simple) Warn on delete of a raw pointer that is not an owner. Suggest use of standard-library resource handle or use of owner.(简单)在删除原始指针而不是owner时报警。建议使用标准库中的资源句柄或者owner

(Simple) Warn on failure to either reset or explicitly delete an owner pointer on every code path.(简单)如果任何代码路径上的owner指针的重置或删除操作发生失败,报警。

(Simple) Warn if the return value of new or a function call with an owner return value is assigned to a raw pointer or non-owner reference.(简单)如果new或者返回owner的函数调用的结果被分配给原始指针或者非owner引用,报警。

本页共63段,3686个字符,5163 Byte(字节)